package com.syuchen.register.redisRegister;

import com.syuchen.common.URL;
import org.redisson.Redisson;
import org.redisson.api.RSet;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * todo 将注册中心分离出来单独作为一个节点运行
 */
public class RedisRegister {

    private static volatile RedissonClient redisson;

    /**
     * 本地缓存
     */
    private static ConcurrentHashMap<String, HashSet<URL>> urlCacheMap = new ConcurrentHashMap<>();

    private final static String DEFAULT_TOPIC = "DEFAULT_TOPIC";

    static {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://localhost:9999");
        // 创建RedissonClient实例
        redisson = Redisson.create(config);
    }

    public static void register(String interfaceName, URL url) {
        RSet<URL> set = redisson.getSet("service:" + interfaceName);
        set.add(url);
        RTopic topic = redisson.getTopic(DEFAULT_TOPIC);
        topic.publish(new UrlChangeMsg(UrlChangeMsg.ADD_TYPE, interfaceName, url));
    }

    public static void unRegister(String interfaceName, URL url) {
        RSet<URL> set = redisson.getSet("service:" + interfaceName);
        set.remove(url);
        RTopic topic = redisson.getTopic(DEFAULT_TOPIC);
        topic.publish(new UrlChangeMsg(UrlChangeMsg.DELETE_TYPE, interfaceName, url));
    }

    public static List<URL> getServiceUrls(String interfaceName) {
        List<URL> result;
        if (urlCacheMap.get(interfaceName) == null) {
            RSet<URL> set = redisson.getSet("service:" + interfaceName);
            urlCacheMap.put(interfaceName, new HashSet<>(set));
            if (subTopic == null) subUrlChangeMsg();
            result = new ArrayList<>(set);
        } else {
            result = new ArrayList<>(urlCacheMap.get(interfaceName));
        }
        return result;
    }

    private static RTopic subTopic;
    private static void subUrlChangeMsg() {
        if (subTopic == null) {
            synchronized (RedisRegister.class) {
                if (subTopic == null) {
                    subTopic = redisson.getTopic(DEFAULT_TOPIC);
                    subTopic.addListener(UrlChangeMsg.class, (channel, msg) -> {
                        HashSet<URL> urls = urlCacheMap.get(msg.interfaceName);
                        if (msg.type == UrlChangeMsg.ADD_TYPE) {
                            if (urls != null) urls.add(msg.url);
                            else {
                                urls = new HashSet<>();
                                urls.add(msg.url);
                                urlCacheMap.put(msg.interfaceName, urls);
                            }
                        } else if (msg.type == UrlChangeMsg.DELETE_TYPE) {
                            if (urls != null) urls.remove(msg.url);
                        }
                    });
                }
            }
        }
    }
}
